package com.ctshk.rpc.system.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.crypto.digest.BCrypt;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ctshk.common.constant.RedisConstants;
import com.ctshk.common.enums.SysUserLockStatus;
import com.ctshk.common.enums.SystemError;
import com.ctshk.common.enums.UserStatus;
import com.ctshk.common.exception.BusinessException;
import com.ctshk.common.mail.core.MailTemplate;
import com.ctshk.common.model.PageResponse;
import com.ctshk.common.model.TokenUser;
import com.ctshk.common.utils.EntityUtil;
import com.ctshk.common.utils.MD5Util;
import com.ctshk.rpc.system.dto.MainDataFieldDataDTO;
import com.ctshk.rpc.system.dto.UserDTO;
import com.ctshk.rpc.system.entity.MainDataFieldData;
import com.ctshk.rpc.system.entity.SysDepartment;
import com.ctshk.rpc.system.entity.SysUser;
import com.ctshk.rpc.system.mapper.MainDataFieldDataMapper;
import com.ctshk.rpc.system.mapper.SysDepartmentMapper;
import com.ctshk.rpc.system.mapper.SysRoleMapper;
import com.ctshk.rpc.system.mapper.SysUserMapper;
import com.ctshk.rpc.system.req.AddSysUserReq;
import com.ctshk.rpc.system.req.QuerySysUserReq;
import com.ctshk.rpc.system.req.UpdateMyInfoReq;
import com.ctshk.rpc.system.service.IMainDataFieldDataService;
import com.ctshk.rpc.system.service.ISysPermissionService;
import com.ctshk.rpc.system.service.ISysUserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.transaction.annotation.Transactional;

import javax.mail.MessagingException;
import java.io.Serializable;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author 谢诗宏
 * @description 用户service实现类
 * @date 2020/12/9
 */
@Slf4j
@DubboService
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements ISysUserService {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    private SysDepartmentMapper sysDepartmentMapper;
    @Autowired
    private SysRoleMapper sysRoleMapper;
    @Autowired
    private ISysPermissionService sysPermissionService;
    @Autowired
    private IMainDataFieldDataService mainDataFieldDataService;
    @Autowired
    private MainDataFieldDataMapper mainDataFieldDataMapper;
    @Autowired
    private MailTemplate mailTemplate;

    @Override
    public UserDTO getByUserId(Long userId) {
        SysUser sysUser = sysUserMapper.selectById(userId);
        if (sysUser == null || sysUser.getIsDeleted() == 1) {
            throw new BusinessException(SystemError.USER_1002);
        }
        UserDTO userDto = new UserDTO();
        if (sysUser != null) {
            BeanUtils.copyProperties(sysUser, userDto);
            SysDepartment sysDepartment = sysDepartmentMapper.selectById(userDto.getDeptId());
            userDto.setDept(sysDepartment.getTitle());
            userDto.setDeptCode(sysDepartment.getDeptCode());
        }
        return userDto;
    }

    @Override
    public boolean verifyTheFormat(String str) {
        String regex1 = ".*[a-zA-Z]+.*";//包含大小写字母
        String regex2 = ".*[0-9]+.*";//包含数字
        String regex3 = ".*[_`~!@#$%^&*()+=|{}:;',\\[\\].<>/?]+.*";//包含特殊字符
        Matcher m1 = Pattern.compile(regex1).matcher(str);
        Matcher m2 = Pattern.compile(regex2).matcher(str);
        Matcher m3 = Pattern.compile(regex3).matcher(str);
        return m1.matches() && m2.matches() && m3.matches();
    }

    @Override
    public UserDTO login(UserDTO u) {
        QueryWrapper<SysUser> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(SysUser::getUsername, u.getUsername())
                .eq(SysUser::getStatus, 1)
                .eq(SysUser::getIsDeleted, 0);
        SysUser sysUser = sysUserMapper.selectOne(wrapper);
        if (sysUser == null) {
            throw new BusinessException(SystemError.USER_1002);
        }
        String lockoutKey = RedisConstants.ACCOUNT_LOCKOUT + sysUser.getId();
        Object lockout = redisTemplate.opsForValue().get(lockoutKey);
        if (null != lockout) {
            throw new BusinessException(SystemError.USER_1004);
        }
        if (!BCrypt.checkpw(u.getPassword(), sysUser.getPassword())) {
            // 增加当天登录错误次数,每天5次
            String key = RedisConstants.ACCOUNT_LOCKOUT_TIMES + sysUser.getUsername();
            Object lockoutTimes = redisTemplate.opsForValue().get(key);
            int count = 1;
            if (null != lockoutTimes) {
                count = Integer.parseInt(lockoutTimes.toString()) + 1;
            }
            redisTemplate.opsForValue().set(key, count, 24, TimeUnit.HOURS);
            if (count >= 5) {
                //不给过期时间，让他找管理员手动解锁
                redisTemplate.opsForValue().set(lockoutKey, 1);
                throw new BusinessException(SystemError.USER_1004);
            }
            throw new BusinessException(SystemError.USER_1003, 5 - count);
        }
        LocalDateTime lastChangePwd = sysUser.getLastChangePwd();
        LocalDateTime end = LocalDateTime.now();
        Duration duration = Duration.between(lastChangePwd, end);
        log.info("上次修改密码时间[{}],已经[{}]天", lastChangePwd, duration.toDays());
        if (duration.toDays() >= 90) {
            throw new BusinessException(SystemError.USER_1010);
        }
        UserDTO userDto = new UserDTO();

        BeanUtils.copyProperties(sysUser, userDto);
        // userDto.setFullName(StrUtil.concat(true, sysUser.getCnSurname(), sysUser.getCnName()));
        log.info("userDto[{}]", userDto);
        getDept(userDto);//设置部门
        return userDto;
    }

    @Override
    public UserDTO getUser(UserDTO u) {
        SysUser sysUser = sysUserMapper.selectOne(Wrappers.<SysUser>lambdaQuery().eq(SysUser::getUsername, u.getUsername()));
        if (sysUser == null) {
            throw new BusinessException(SystemError.USER_1002);
        }
        UserDTO userDto = new UserDTO();
        BeanUtils.copyProperties(sysUser, userDto);
        getDept(userDto);//设置部门
        return userDto;
    }

    @Override
    public PageResponse<UserDTO> listUser(QuerySysUserReq querySysUserReq, TokenUser currentUser) {
        /*Result<List<Long>> permissionResult = sysPermissionService.queryPermission(querySysUserReq.getMenuId(), currentUser.getId());
        if (!permissionResult.isSuccess()) {
            SystemError result = SystemError.getDefined(permissionResult.getCode());
            throw new BusinessException(result);
        }*/
        // 分页条件查询
        QueryWrapper<SysUser> wrapper = new QueryWrapper<>();
        wrapper.lambda()
                .eq(querySysUserReq.getStatus() != null, SysUser::getStatus, querySysUserReq.getStatus())
                .eq(SysUser::getIsDeleted, 0)
                .eq(querySysUserReq.getId() != null, SysUser::getId, querySysUserReq.getId())
                .eq(StringUtils.isNotEmpty(querySysUserReq.getDeptId()), SysUser::getDeptId, querySysUserReq.getDeptId())
                .eq(StringUtils.isNotEmpty(querySysUserReq.getRole()), SysUser::getRoles, querySysUserReq.getRole())
                .eq(StringUtils.isNotEmpty(querySysUserReq.getPosition()), SysUser::getPosition, querySysUserReq.getPosition());
        if (StringUtils.isNotEmpty(querySysUserReq.getSearchName())) {
            //这个地方要拼接姓和名
            wrapper.and(e -> e
                    .like("CONCAT(cn_surname,cn_name)", querySysUserReq.getSearchName())
                    .or().like("CONCAT(en_surname,en_name)", querySysUserReq.getSearchName())
                    .or().like("username", querySysUserReq.getSearchName())
                    .or().like("employee_number", querySysUserReq.getSearchName())
                    .or().like("mobile", querySysUserReq.getSearchName())
                    .or().like("email", querySysUserReq.getSearchName())
            );
        }
        wrapper.lambda().orderByDesc(SysUser::getId);
        Page<SysUser> iPage = new Page<>(querySysUserReq.getPageNo(), querySysUserReq.getPageSize());
        IPage<SysUser> sysUsers = sysUserMapper.selectPage(iPage, wrapper);
        if (CollectionUtils.isEmpty(sysUsers.getRecords())) {
            return PageResponse.empty(sysUsers.getCurrent());
        }
        Integer lock = querySysUserReq.getLocked();
        List<UserDTO> userDTOS = new ArrayList<>();
        sysUsers.getRecords().forEach(sysUser -> {
            UserDTO userDTO = EntityUtil.copy(sysUser, UserDTO.class);
            // userDTO.setFullName(StrUtil.concat(true, sysUser.getCnSurname(), sysUser.getCnName()));
            // 英文名姓氏在前
            // userDTO.setEnglishName(StrUtil.concat(true, sysUser.getEnName(), sysUser.getEnSurname()));

            // 获取账号上级部门
            getDept(userDTO);//设置部门

            // 获取账号角色
//            if (StringUtils.isNotBlank(sysUser.getRoles())) {
//                String roleName = sysRoleMapper.getRoleName(sysUser.getRoles());
////                userDTO.setRoles(roleName);//这里注释掉，和职位一样返回主数据id给前端
//            }

            // TODO 获取职位信息,等主数据实现后继续完善。。。

            // 获取账号锁定状态
            String lockoutKey = RedisConstants.ACCOUNT_LOCKOUT + sysUser.getId();
            Object lockout = redisTemplate.opsForValue().get(lockoutKey);
            if (null != lockout) {
                userDTO.setLocked(true);
            } else {
                userDTO.setLocked(false);
            }
            //判断查询有没有加锁状态判断
            if (lock != null) {
                //当前数据为锁定状态  并且  锁筛选条件为锁定 才加入集合
                if (userDTO.getLocked() && lock == SysUserLockStatus.LOCK.getCode()) {
                    userDTOS.add(userDTO);
                }
                //当前数据为解锁状态  并且  锁筛选条件为解锁状态 才加入集合
                if (!userDTO.getLocked() && lock == SysUserLockStatus.UNLOCK.getCode()) {
                    userDTOS.add(userDTO);
                }
            } else {
                //没有筛选锁状态  全部加入集合
                userDTOS.add(userDTO);
            }
        });
        PageResponse<UserDTO> result = new PageResponse<>(userDTOS, sysUsers.getCurrent() == 1,
                sysUsers.getTotal() <= (sysUsers.getCurrent() * sysUsers.getSize()),
                sysUsers.getTotal(), sysUsers.getCurrent(), sysUsers.getSize());
        return result;
    }

    @Override
    public PageResponse<UserDTO> users(QuerySysUserReq querySysUserReq) {
        Page<UserDTO> iPage = new Page<>(querySysUserReq.getPageNo(), querySysUserReq.getPageSize());
        IPage<UserDTO> sysUsers = sysUserMapper.pageUser(iPage);

        PageResponse<UserDTO> result = new PageResponse<>(sysUsers.getRecords(), sysUsers.getCurrent() == 1, sysUsers.getTotal() <= (sysUsers.getCurrent() * sysUsers.getSize()), sysUsers.getTotal(), sysUsers.getCurrent(), sysUsers.getSize());

        return result;
    }

    @Override
    public UserDTO loadUserByParam(Object param, Integer queryType) {
        SysUser sysUser;
        if (queryType == 1) {
            sysUser = sysUserMapper.selectById((Serializable) param);
        } else if (queryType == 2) {
            sysUser = sysUserMapper.selectOne(Wrappers.<SysUser>lambdaQuery().eq(SysUser::getUsername, param));
        } else {
            sysUser = sysUserMapper.selectOne(Wrappers.<SysUser>lambdaQuery().eq(SysUser::getEmail, param));
        }
        if (sysUser == null || sysUser.getIsDeleted() == 1) {
            throw new BusinessException(SystemError.USER_1002);
        }
        UserDTO userDto = new UserDTO();
        if (sysUser != null) {
            BeanUtils.copyProperties(sysUser, userDto);
            getDept(userDto);//设置部门
        }
        return userDto;
    }

    @Override
    public UserDTO loadUserInfo(Object param, Integer queryType) {
        SysUser sysUser;
        if (queryType == 1) {
            sysUser = sysUserMapper.selectById((Serializable) param);
        } else if (queryType == 2) {
            sysUser = sysUserMapper.selectOne(Wrappers.<SysUser>lambdaQuery().eq(SysUser::getUsername, param));
        } else {
            sysUser = sysUserMapper.selectOne(Wrappers.<SysUser>lambdaQuery().eq(SysUser::getEmail, param));
        }
        if (sysUser == null) {
            return null;
        }
        UserDTO userDto = new UserDTO();
        if (sysUser != null) {
            BeanUtils.copyProperties(sysUser, userDto);
        }
        return userDto;
    }

    @Override
    public UserDTO queryCacheUser(long userId) {
        Object userDtoRedis = redisTemplate.opsForValue().get(RedisConstants.ACCOUNT_QUERY_KEY + userId);
        UserDTO userDto = null;
        if (userDtoRedis == null) {
            insertCacheUser();
            userDto = (UserDTO) redisTemplate.opsForValue().get(RedisConstants.ACCOUNT_QUERY_KEY + userId);
        } else {
            userDto = (UserDTO) redisTemplate.opsForValue().get(RedisConstants.ACCOUNT_QUERY_KEY + userId);
        }
        return userDto;
    }

    @Override
    public List<UserDTO> queryCacheUsers(Set<Long> userIds) {
        List<UserDTO> userDTOs = new ArrayList<>();
        for (Long userId : userIds) {
            UserDTO userDto = (UserDTO) redisTemplate.opsForValue().get(RedisConstants.ACCOUNT_QUERY_KEY + userId);
            if (userDto == null) {
                insertCacheUser();
                userDto = (UserDTO) redisTemplate.opsForValue().get(RedisConstants.ACCOUNT_QUERY_KEY + userId);
            }
            userDTOs.add(userDto);
        }
        return userDTOs;
    }

    @Override
    public void insertCacheUser() {
//        List<SysUser> users = sysUserMapper.selectList(null);
        List<UserDTO> userDTOS = sysUserMapper.selectDTOList();
        userDTOS.forEach(user -> {
            try {
                SysDepartment department = sysDepartmentMapper.selectById(user.getDeptId());
                if (department != null) {
                    user.setDept(department.getTitle());
                    user.setDeptNumber(department.getDeptNumber());
                    user.setDeptCostCode(department.getCostCode());
                }
                redisTemplate.opsForValue().set(RedisConstants.ACCOUNT_QUERY_KEY + user.getId(), user);
            } catch (Exception e) {
                log.error("用户[{}]插入缓存失败,错误信息[{}]", user.getId(), e.getMessage());
            }
        });
    }

    @Override
    public int resetPassword(long userId, String password) {
        SysUser sysUser = new SysUser();
        sysUser.setId(userId);
        sysUser.setPassword(BCrypt.hashpw(password, BCrypt.gensalt()));
        sysUser.setLastChangePwd(LocalDateTime.now());

        return sysUserMapper.updateById(sysUser);
    }

    @Override
    public long addUser(AddSysUserReq addSysUserReq, long userId) {
        SysUser sysUser = EntityUtil.copy(addSysUserReq, SysUser.class);
        Long id = IdWorker.getId();
        sysUser.setId(id);
        sysUser.setCreateId(userId);
        sysUser.setPassword(BCrypt.hashpw(addSysUserReq.getUsername(), BCrypt.gensalt()));
        //新建的用戶在沒有設置權限的時候，其狀態為無效      ---产品说要改成默认有效
        sysUser.setStatus(UserStatus.ENABLE.getCode());
        int insert = sysUserMapper.insert(sysUser);
        //新建成功后像用户邮箱发送一封邮件重置密码
        if (insert > 0) {
            try {
                log.info(id + "创建账号发送邮件。。。");
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            mailTemplate.sendHtmlMail(sysUser.getEmail(),
                                    "香港中旅社雲平臺新賬戶開通信息通知",
                                    getTemplate(sysUser.getCnSurname() + sysUser.getCnName(),
                                            sysUser.getUsername(), sysUser.getEmployeeNumber(), id));
                        } catch (Exception e) {
                            throw new BusinessException(SystemError.SYS_429);
                        }
                    }
                }).start();
            } catch (Exception me3) {
                log.error("发送用户新建重置账号密码邮件错误，错误的信息：" + me3.getMessage());
            }
        }
        return sysUser.getId();
    }

    @Override
    public int del(long id, long userId) {
        SysUser sysUser = sysUserMapper.selectById(id);
        if (sysUser == null || sysUser.getIsDeleted() == 1) {
            throw new BusinessException(SystemError.USER_1002);
        }
        sysUser.setModifiedId(userId);
        sysUser.setIsDeleted(1);

        return sysUserMapper.updateById(sysUser);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int update(AddSysUserReq addSysUserReq, long userId) {
        if (addSysUserReq.getId() == null) {
            throw new BusinessException(SystemError.SYS_402);
        }
        SysUser sysUser = sysUserMapper.selectById(addSysUserReq.getId());
        if (sysUser == null || sysUser.getIsDeleted() == 1) {
            throw new BusinessException(SystemError.USER_1002);
        }
        sysUser = EntityUtil.copy(addSysUserReq, SysUser.class);
        sysUser.setModifiedId(userId);

        return sysUserMapper.updateById(sysUser);
    }

    @Override
    public void updateMyInfo(UpdateMyInfoReq req, Long userId) {
        SysUser sysUser = EntityUtil.copy(req, SysUser.class);
        sysUser.setId(userId);
        sysUser.setModifiedId(userId);
        sysUser.setGmtModified(LocalDateTime.now());
        updateById(sysUser);

    }

    @Override
    public void updateAvatar(String avatar, Long userId) {
        SysUser sysUser = new SysUser();
        sysUser.setId(userId);
        sysUser.setModifiedId(userId);
        sysUser.setGmtModified(LocalDateTime.now());
        sysUser.setAvatar(avatar);
        updateById(sysUser);
    }

    @Override
    public List<UserDTO> getUsers(Set<Long> ids) {
        List<SysUser> list = baseMapper.selectBatchIds(ids);
        List<UserDTO> userDTOS = EntityUtil.copyList(list, UserDTO.class);
        return userDTOS;
    }

    /**
     * 填充角色信息
     * 填充部门信息
     *
     * @param userDto
     */
    private void getDept(UserDTO userDto) {
        getRoles(userDto);//填充角色信息
        getPosition(userDto);//填充职位信息
        // 获取账号上级部门
        if (userDto.getDeptId() != null) {
            List<SysDepartment> sysDepartments = sysDepartmentMapper.selectParents(userDto.getDeptId());
            StringBuilder dept = new StringBuilder();
            if (CollUtil.isNotEmpty(sysDepartments)) {
                //产品说只显示直系部门
//                if(sysDepartments.get(sysDepartments.size()-1) != null){
//                    dept.append(sysDepartments.get(sysDepartments.size()-1).getTitle());
//                }
                int i = 0;
                for (SysDepartment sysDepartment : sysDepartments) {
                    if (i == 2) {
                        // 只获取两级部门
                        break;
                    }
                    dept.append(i == 0 ? "" : "/");
                    dept.append(sysDepartment.getTitle());
                    i++;
                }
                userDto.setDeptCode(sysDepartments.get(sysDepartments.size() - 1).getDeptCode());
            }
            userDto.setDept(String.valueOf(dept));
        }
    }

    private void getRoles(UserDTO userDto) {
        // 填充角色信息
        String roles = userDto.getRoles();
        if (roles != null) {
            MainDataFieldData mdfd = mainDataFieldDataMapper.selectById(roles);
            if (mdfd != null) {
                userDto.setRoleName(mdfd.getFieldValue());
            }
        }
    }

    private void getPosition(UserDTO userDto) {
        // 填充职位信息（简单主数据）
        String position = userDto.getPosition();
        if (position != null) {
            try {
                MainDataFieldDataDTO mdfd = mainDataFieldDataService.queryFieldData(Long.parseLong(position));
                if (mdfd != null) {
                    //将id存为中文用于展示
                    userDto.setPositionName(mdfd.getFieldValue());
                }
            } catch (Exception e) {
                //已经是中文了
            }
        }
    }

    /**
     * 获取模板
     *
     * @param name      用户中文名称
     * @param loginName 登录名
     * @param number    员工编号
     * @return
     */
    private String getTemplate(String name, String loginName, String number, Long id) {
        String url = "http://47.243.8.56:9090/user/set-password";
        String key = loginName + RandomUtil.randomNumbers(4) + number;
        String md5Token = MD5Util.stringMd5(key);
        //这个key在3天后生效
        redisTemplate.opsForValue().set(md5Token, id, 3, TimeUnit.DAYS);
        StringBuffer sb = new StringBuffer();
        sb.append("<!DOCTYPE HTML>\n");
        sb.append("<html lang=\"en-US\">\n");
        sb.append("<head>\n");
        sb.append("\t<meta charset=\"UTF-8\">\n");
        sb.append("\t<title>賬號創建成功郵件</title>\n");
        sb.append("\t<style type=\"text/css\">\n");
        sb.append("\t\t.template{\n");
        sb.append("\t\t\twidth: 800px;\n");
        sb.append("\t\t\tmargin: 50px auto 0px auto;\n");
        sb.append("\t\t}\n");
//        sb.append("\t\tspan{\n");
//        sb.append("\t\t\tcolor:red;\n");
//        sb.append("\t\t}\n");
        sb.append("\t\tp,a{\n");
        sb.append("\t\t\tpadding-left:2em;\n");
        sb.append("\t\t}\n");
        sb.append("\t</style>\n");
        sb.append("</head>\n");
        sb.append("<body>\n");
        sb.append("\t<div class=\"template\" >\n");
//        sb.append("\t\t<img src=\"https://ctshk-cloud-dev.oss-cn-hongkong.aliyuncs.com/logo.png\"/>\n");
//        sb.append("\t\t<hr/>\n");
        sb.append("\t\t<h3>Dear <span>" + name + "</span>：</h3>\n");
        sb.append("\t\t<p>您好，您的雲平台賬戶已創建成功。</p>\n");
        sb.append("\t\t<p>登錄名是：<span>" + loginName + "</span></p>\n");
        sb.append("\t\t<p>爲了您的賬戶安全，請通過點擊以下鏈接设置登錄密碼。</p>\n");
        sb.append("\t\t<a href=\"" + url + "?key=" + md5Token + "\"><span>点击这里</span></a>\n");
        sb.append("\t\t<p>如果鏈接無法點擊，請將鏈接複製並粘貼至瀏覽器窗口上打開。</p>\n");
        sb.append("\t\t<br/>\n");
        sb.append("\t\t<p>Hello, your Cloud Platform account has been created successfully.</p>\n");
        sb.append("\t\t<p>Your account is <span>" + loginName + "</span>.</p>\n");
        sb.append("\t\t<p>For your account security,please login and change your password by clicking the following link.</p>\n");
        sb.append("\t\t<a href=\"" + url + "?key=" + md5Token + "\"+md5Token+\"\"><span>click here</span></a>\n");
        sb.append("\t\t<p>If the above link cannot be clicked,please copy and paste it into the browser.</p>\n");
        sb.append("\t</div>\n");
        sb.append("</body>\n");
        sb.append("</html>");
        return sb.toString();
    }

    public static void main(String[] arges) {
        System.out.println(MD5Util.stringMd5("189739462874822705567"));
    }
}
